Skip to content

GODRIVER-3037 Support internal-only options. #2023

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 1, 2025

Conversation

qingyang-hu
Copy link
Collaborator

@qingyang-hu qingyang-hu commented Apr 16, 2025

GODRIVER-3037

Summary

Support setting internal-only options with a helper function.

Background & Motivation

This proposal does not change the current interface.
The option names are not publicly exposed to the user, so it is less likely to be used without internal knowledge.
We can add a map[string]any named custom in ClientOptions struct for future internal options, such as AuthenticateToAnything.
The Crypt and Deployment fields in ClientOptions will be merged into the aforementioned map in v3.

@mongodb-drivers-pr-bot mongodb-drivers-pr-bot bot added the priority-3-low Low Priority PR for Review label Apr 16, 2025
Copy link
Contributor

mongodb-drivers-pr-bot bot commented Apr 16, 2025

API Change Report

./v2/mongo/options

compatible changes

ClientOptions.Custom: added

./v2/x/mongo/driver/xoptions

compatible changes

package added

@qingyang-hu qingyang-hu marked this pull request as ready for review April 17, 2025 15:18
@qingyang-hu qingyang-hu requested a review from a team as a code owner April 17, 2025 15:18
// SetInternalClientOptions sets internal options for ClientOptions.
//
// Deprecated: This function is for internal use only. It may be changed or removed in any release.
func SetInternalClientOptions(opts *ClientOptions, custom map[string]any) (*ClientOptions, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this function live in the experimental API? What is the pattern for future custom data? Should ClientOptions be extended with a Custom field of type map[string]any?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider the following pattern:

type ClientOptions struct {
	custom map[string]any
}

func WithCustomValue(co ClientOptions, key string, val any) ClientOptions {}
func CustomValue(co ClientOptions key string) any {}

Then in x/mongo/driver:

const someExperimentKey = "x/mongo/driver:myExperiment"

func WithSomeExperimentValue(co options.ClientOptions, on bool) options.ClientOptions {
	return options.WithCustomValue(co, someExperimentKey, on)
}

func SomeExperimentValue(co options.ClientOptions) bool {
	val := options.CustomValue(co, someExperimentKey)
	if b, ok := val.(bool); ok {
		return b
	}

	return false
}

The usage would look something like this:

	clientOpts, _ := options.Client()
	clientOpts = driver.WithSomeExperimentValue(clientOpts, true)

	// ...

And we would check it internally like this:

	expVal := driver.SomeExperimentValue(clientOpts)
	// ...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of an expressive interface, I'd prefer a map-style interface without any hint other than a user-provided option name to add obfuscation to discourage general users from using it. However, it makes sense to wrap the map[string]any in a struct and move it to "x/mongo/driver" to emphasize it is "experimental".

I can stack another PR for GODRIVER-3429 (internal-only "AuthenticateToAnything") on top of this one to demonstrate future custom data.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this solution is fine for now, we can update if needed later.

prestonvasquez
prestonvasquez previously approved these changes Apr 22, 2025
// not use this file except in compliance with the License. You may obtain
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

package options
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we name this package something different to avoid import conflicts? Perhaps xoptions?

// SetInternalClientOptions sets internal options for ClientOptions.
//
// Deprecated: This function is for internal use only. It may be changed or removed in any release.
func SetInternalClientOptions(opts *options.ClientOptions, key string, option any) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this to return an error? Should we just do nothing if an unsupported option is set?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to keep the return to avoid silent errors, for example, a typo in the key name. Otherwise, these errors would be difficult to find.

@qingyang-hu qingyang-hu merged commit 50523c2 into mongodb:master May 1, 2025
27 of 34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority-3-low Low Priority PR for Review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants